package org.krtrain.sports.tracker;

import java.util.HashMap;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.krtrain.sports.player.Player;
import org.kuali.rice.krad.service.BusinessObjectService;
import org.kuali.rice.krad.service.KRADServiceLocator;
import org.kuali.rice.krad.uif.UifParameters;
import org.kuali.rice.krad.util.GlobalVariables;
import org.kuali.rice.krad.util.KRADConstants;
import org.kuali.rice.krad.web.controller.UifControllerBase;
import org.kuali.rice.krad.web.form.UifFormBase;
import org.springframework.stereotype.Controller;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.servlet.ModelAndView;

import edu.sampleu.SampleuConstants;

/**
 * @author Kuali Rice Team (rice.collab@kuali.org)
 */
@Controller
@RequestMapping(value = "/gametracker")
public class GameTrackerController extends UifControllerBase {

    protected GameTrackerForm createInitialForm(HttpServletRequest request) {
        return new GameTrackerForm();
    }

    /**
     * Retrieve the Game instance based on id and if requesting recap setup totals
     */
    @Override
    @RequestMapping(method = RequestMethod.GET, params = "methodToCall=start")
    public ModelAndView start(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;
        Game game = trackerForm.getGame();

        if (StringUtils.isNotBlank(game.getGameId())) {
            game = getBusinessObjectService().findBySinglePrimaryKey(Game.class, trackerForm.getGame().getGameId());
            trackerForm.setGame(game);
        }

        // check if game needs to be setup
        if (StringUtils.isNotBlank(game.getHomeTeamName()) && StringUtils.isNotBlank(game.getVisitingTeamName()) && game
                .getPlayerStats().isEmpty()) {
            GameUtils.setupGame(game);
        }

        String pageId = trackerForm.getPageId();
        if ("GameTracker-RecapPage".equals(pageId)) {
            GameUtils.computeTotals(trackerForm.getGame(), trackerForm.getHomeTeamStats(), 1);
            GameUtils.computeTotals(trackerForm.getGame(), trackerForm.getVisitingTeamStats(), 2);
        }

        return super.start(form, result, request, response);
    }

    /**
     * Invoked after the home and visiting teams are entered to retrieve the players
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=setupGame")
    public ModelAndView setupGame(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        // refresh both teams to get the players
        Game game = trackerForm.getGame();
        GameUtils.setupGame(game);

        // save game
        getBusinessObjectService().save(game);

        return updateComponent(form, result, request, response);
    }

    /**
     * Substitutes a player in and does player count check
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=substituteIn")
    public ModelAndView substituteIn(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        // get the selected player
        int selectedLineIndex = -1;
        String selectedLine = form.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
        if (StringUtils.isNotBlank(selectedLine)) {
            selectedLineIndex = Integer.parseInt(selectedLine);
        }

        PlayerStatistics playerStatistics = trackerForm.getGame().getPlayerStats().get(selectedLineIndex);
        trackerForm.getInPlayers().add(playerStatistics.getPlayer());

        // count number of players for team
        checkPlayerInCount(trackerForm, playerStatistics.getTeamName());

        return updateComponent(form, result, request, response);
    }

    /**
     * Substitutes a player out and does player count check
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=substituteOut")
    public ModelAndView substituteOut(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        // get the selected player
        int selectedLineIndex = -1;
        String selectedLine = form.getActionParamaterValue(UifParameters.SELECTED_LINE_INDEX);
        if (StringUtils.isNotBlank(selectedLine)) {
            selectedLineIndex = Integer.parseInt(selectedLine);
        }

        PlayerStatistics playerStatistics = trackerForm.getGame().getPlayerStats().get(selectedLineIndex);
        trackerForm.getInPlayers().remove(playerStatistics.getPlayer());

        // count number of players for team
        checkPlayerInCount(trackerForm, playerStatistics.getTeamName());

        return updateComponent(form, result, request, response);
    }

    /**
     * Saves the current game
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=save")
    public ModelAndView save(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;
        Game game = trackerForm.getGame();

        // check if game needs to be setup
        if (game.getPlayerStats().isEmpty()) {
            GameUtils.setupGame(game);
        }

        // save game
        getBusinessObjectService().save(game);

        // add game created msg
        GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES,
                SampleuConstants.KeyConstants.GAME_SAVED_MSG);

        return getUIFModelAndView(form);
    }

    /**
     * Starts or ends a timeout
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=timeout")
    public ModelAndView timeout(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        // toggle timeout
        trackerForm.setTimeoutInProgress(!trackerForm.isTimeoutInProgress());

        return getUIFModelAndView(form);
    }

    /**
     * Saves a game play and returns the play description in the map response
     */
    @RequestMapping(method = RequestMethod.GET, params = "methodToCall=saveGamePlay")
    public
    @ResponseBody
    Map<String, String> saveGamePlay(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        Game game = trackerForm.getGame();
        GamePlay play = new GamePlay();
        play.setGameId(game.getGameId());

        // get player by number
        Player player = getBusinessObjectService().findBySinglePrimaryKey(Player.class,
                trackerForm.getNewGamePlayNumber());
        play.setPlayerNumber(player.getNumber());
        play.setTeamName(player.getTeamName());

        String playDescription = GameUtils.buildGamePlayDescription(player, trackerForm.getNewGamePlayProperty(),
                trackerForm.getNewGamePlayMinutes(), trackerForm.getNewGamePlaySeconds(),
                trackerForm.getNewGamePlayHalf());
        play.setPlayDescription(playDescription);
        game.getGamePlays().add(play);

        Map<String, String> saveRsp = new HashMap<String, String>();
        saveRsp.put("playDesc", playDescription);

        return saveRsp;
    }

    protected void checkPlayerInCount(GameTrackerForm trackerForm, String teamName) {
        // count number of players for team
        int playerCnt = 0;
        for (Player inPlayer : trackerForm.getInPlayers()) {
            if (teamName.equals(inPlayer.getTeamName())) {
                playerCnt++;
            }
        }

        // check number of players
        if (playerCnt > 5) {
            GlobalVariables.getMessageMap().putWarning("GameTracker-PlayersTabGroup",
                    SampleuConstants.KeyConstants.GAME_SUBS_OUT_WARN);
        } else if (playerCnt < 5) {
            GlobalVariables.getMessageMap().putWarning("GameTracker-PlayersTabGroup",
                    SampleuConstants.KeyConstants.GAME_SUBS_IN_WARN);
        }
    }

    /**
     * Handles menu navigation between view pages
     */
    @RequestMapping(method = RequestMethod.POST, params = "methodToCall=navigate")
    public ModelAndView navigate(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
            HttpServletRequest request, HttpServletResponse response) {
        GameTrackerForm trackerForm = (GameTrackerForm) form;

        String pageId = form.getActionParamaterValue(UifParameters.NAVIGATE_TO_PAGE_ID);
        if ("GameTracker-RecapPage".equals(pageId)) {
            GameUtils.computeTotals(trackerForm.getGame(), trackerForm.getHomeTeamStats(), 1);
            GameUtils.computeTotals(trackerForm.getGame(), trackerForm.getVisitingTeamStats(), 2);
        }

        return super.navigate(form, result, request, response);
    }

    protected BusinessObjectService getBusinessObjectService() {
        return KRADServiceLocator.getBusinessObjectService();
    }
}
